package com.pactera.asmp.server.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.page.PageMethod;
import com.google.common.collect.Lists;
import com.pactera.asmp.server.common.constants.Constants;
import com.pactera.asmp.server.common.constants.ResultCode;
import com.pactera.asmp.server.common.exception.CustomException;
import com.pactera.asmp.server.common.logprint.utils.CollectionUtils;
import com.pactera.asmp.server.config.MinioConfig;
import com.pactera.asmp.server.dao.ProjectMapper;
import com.pactera.asmp.server.dao.TPluginConfigMapper;
import com.pactera.asmp.server.pojo.ProjectInfo;
import com.pactera.asmp.server.pojo.TPluginConfig;
import com.pactera.asmp.server.pojo.TPluginConfigExample;
import com.pactera.asmp.server.pojo.User;
import com.pactera.asmp.server.utils.ApplicationContextUtil;
import com.pactera.asmp.server.utils.AssertUtil;
import com.pactera.asmp.server.utils.PageDataResult;

import org.apache.shiro.SecurityUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

/**
 * @ProjectName: asmp-server
 * @Package com.pactera.asmp.server.service
 * @ClassName: PluginConfigServiceImpl
 * @Description: PluginConfigServiceImpl
 * @Date 2020/07/24 16:34
 * @Author lvzhiqiang
 * @Version 1.0
 */
@Service
@Slf4j
public class PluginConfigServiceImpl implements IPluginConfigService {
    @Resource
    private TPluginConfigMapper pluginConfigMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ApplicationContextUtil applicationContextUtil;

    @Resource
    public ProjectMapper mProjectMapper;

    @Autowired
    private MinioConfig minioConfig;

//    @Autowired
//    private SeaweedFSConfig seaweedFSConfig;

    @Override
    public int insert(TPluginConfig pluginConfig) {
        int count = 0;
        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (null == currUser) {
            throw new CustomException(ResultCode.PERMISSION_EXPIRE);
        }

        AssertUtil.notNull(pluginConfig.getProjectId(),"项目Id不允许为空");
        AssertUtil.notNull(pluginConfig.getServerAddress(),"服务地址不允许为空");

        pluginConfig.setStatus((byte) -1);
        pluginConfig.setIsUse((byte) 0);
        pluginConfig.setCreateUserId(currUser.getId());
        pluginConfig.setCreateUserName(currUser.getUsername());
        Date date = new Date();
        pluginConfig.setCreateTime(date);
        pluginConfig.setUpdateTime(date);
        count = pluginConfigMapper.insert(pluginConfig);

        // 发送到MQ并更新表状态
        try {
            IPluginConfigService pluginConfigService = (IPluginConfigService) applicationContextUtil.getBean(PluginConfigServiceImpl.class);
            pluginConfigService.sendMsgAndChangeStatus(pluginConfig);
        } catch (Exception e) {
            log.error("PluginConfigServiceImpl.sendMsg() error: ", e);
        }

        return count;
    }

    @Override
    public PageDataResult selective(Integer page, Integer limit, Integer projectId) {
        if (null == page || 0 == page.intValue()) {
            page = 1;
        }
        if (null == limit || 0 == limit.intValue()) {
            limit = 10;
        }

        if(page.intValue() < 0 || limit.intValue() < 0) {
            return new PageDataResult(0, Lists.newArrayList());
        }

        TPluginConfigExample exmple = new TPluginConfigExample();
        TPluginConfigExample.Criteria criteria = exmple.createCriteria();
        criteria.andIsUseEqualTo((byte) 0);
        if(null != projectId) {
            criteria.andProjectIdEqualTo(projectId);
        }
        exmple.setOrderByClause("id desc");
        PageMethod.startPage(page, limit);
        List<TPluginConfig> pluginConfigs = pluginConfigMapper.selectByExample(exmple);

        // 把项目Id转化为项目名
        Set<Integer> idSets = new HashSet<>();
        for (TPluginConfig pluginConfig : pluginConfigs) {
            idSets.add(pluginConfig.getProjectId());
        }
        Map<Integer, ProjectInfo> map = this.projectId2Obj(new ArrayList<>(idSets));
        for (TPluginConfig pluginConfig : pluginConfigs) {
            if (map.containsKey(pluginConfig.getProjectId())
                    && null != map.get(pluginConfig.getProjectId())) {
                pluginConfig.setProjectName(map.get(pluginConfig.getProjectId()).getProjectName());
            }
        }
        return new PageDataResult(pluginConfigs.size(), pluginConfigs);
    }

    @Override
    public int update(TPluginConfig pluginConfig) {
        pluginConfig.setUpdateTime(new Date());
        return pluginConfigMapper.updateByPrimaryKeySelective(pluginConfig);
    }

    /**
     * 配置发送到MQ，并更新表状态
     * 若发送到MQ失败，则事务回滚
     * @param pluginConfig
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendMsgAndChangeStatus(TPluginConfig pluginConfig) {
        // 更新插件配置状态为"待生成"
        TPluginConfig pluginConfigNew = new TPluginConfig();
        pluginConfigNew.setId(pluginConfig.getId());
        pluginConfigNew.setStatus((byte) 0);
        pluginConfigMapper.updateByPrimaryKeySelective(pluginConfigNew);

        // 发送到MQ
        rabbitTemplate.convertAndSend(Constants.COMMON_DIRECT_EXCHANGE,
                Constants.PLUGIN_CONFIG_ROUTINGKEY, this.handleSendMqMsg(pluginConfig));
        log.info("sendMsgAndChangeStatus sendMq success id: {}", pluginConfig.getId());
    }

    @Override
    public TPluginConfig detail(Long id) {
        TPluginConfig pluginConfig = pluginConfigMapper.selectByPrimaryKey(id);
        if (null == pluginConfig) {
            return null;
        }
        pluginConfig.setProjectName(mProjectMapper.selectByPrimaryKey(pluginConfig.getProjectId()).getProjectName());
        return pluginConfigMapper.selectByPrimaryKey(id);
    }

    private String handleSendMqMsg(TPluginConfig pluginConfig) {
        ProjectInfo projectInfo = mProjectMapper.selectByPrimaryKey(pluginConfig.getProjectId());
        if (null == projectInfo) {
            log.error("handleSendMqMsg projectInfo is empty!");
            throw new CustomException(ResultCode.RESULT_DATA_NONE);
        }

        // =====================================文件服务器替换代码 start=========================================

//        String systemVersion = "Delphi 27.24.01.31";
//        StringBuilder properties = new StringBuilder()
//                .append("projectName=").append(projectInfo.getProjectName())
//                .append("\n").append("systemVersion=").append(systemVersion)
//                .append("\n").append("baseServerUrl=").append(pluginConfig.getServerAddress())
//                .append("\n").append("asmpHost=").append(seaweedFSConfig.getHost())
//                .append("\n").append("asmpPort=").append(seaweedFSConfig.getPort())
//                .append("\n").append("issueUploadImmediately=").append(true)
//                .append("\n").append("appadCpuInfo=").append(true)
//                .append("\n").append("appendMemoryInfo=").append(true)
//                .append("\n").append("appendActivityTaskInfo=").append(true)
//                .append("\n").append("powerWasteReport=").append(false)
//                .append("\n").append("needUsbLog=").append(false)
//                .append("\n").append("receiveBoot=").append(true)
//                .append("\n").append("configItem=").append(pluginConfig.getConfigItem())
//                .append("\n").append("exceptionDataCollection=").append(pluginConfig.getExceptionDataCollection());


        String url = minioConfig.getUrl();
        URI uri = URI.create(url);
        String systemVersion = "Delphi 27.24.01.31"; // TODO 硬编码
        StringBuilder properties = new StringBuilder()
                .append("projectName=").append(projectInfo.getProjectName())
                .append("\n").append("systemVersion=").append(systemVersion)
                .append("\n").append("baseServerUrl=").append(pluginConfig.getServerAddress())
                .append("\n").append("asmpHost=").append(uri.getHost())
                .append("\n").append("asmpPort=").append(uri.getPort())
                .append("\n").append("issueUploadImmediately=").append(true)
                .append("\n").append("appadCpuInfo=").append(true)
                .append("\n").append("appendMemoryInfo=").append(true)
                .append("\n").append("appendActivityTaskInfo=").append(true)
                .append("\n").append("powerWasteReport=").append(false)
                .append("\n").append("needUsbLog=").append(false)
                .append("\n").append("receiveBoot=").append(true)
                .append("\n").append("configItem=").append(pluginConfig.getConfigItem())
                .append("\n").append("exceptionDataCollection=").append(pluginConfig.getExceptionDataCollection());

        // =====================================文件服务器替换代码 end=========================================

        JSONObject result = new JSONObject();
        result.put("propertiesStr", properties);
        result.put("id", pluginConfig.getId());
        return result.toJSONString();
    }

    private Map<Integer, ProjectInfo> projectId2Obj(List<Integer> list) {
        Map<Integer, ProjectInfo> map = new HashMap<>();
        if (CollectionUtils.isEmpty(list)) {
            return map;
        }
        List<ProjectInfo> projectInfos = mProjectMapper.queryByPrimaryKeys(list);
        if (CollectionUtils.isEmpty(projectInfos)) {
            return map;
        }
        for (ProjectInfo projectInfo : projectInfos) {
            map.put(projectInfo.getId(), projectInfo);
        }
        return map;
    }
}
